import { CdkDragDrop, CdkDrag, CdkDropList, CdkDropListGroup, CdkDragEnter, CdkDragStart } from '@angular/cdk/drag-drop';
import { NgClass, NgStyle } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, viewChild, ViewChild } from '@angular/core';

import { NgDragDropService } from '@app/core/services/common/drag-drop.service';
import { DraggableDirective } from '@app/shared/directives/draggable.directive';
import { DroppableDirective } from '@app/shared/directives/droppable.directive';
import { ResizableModule, ResizeEvent } from 'angular-resizable-element';
import { uniqueId } from 'lodash';
import { NzGridModule } from 'ng-zorro-antd/grid';
import { NzIconDirective } from 'ng-zorro-antd/icon';
import { NzTabPosition, NzTabsModule } from 'ng-zorro-antd/tabs';

import { LayoutPosition, WidgetConfig } from '../widget-default-setting';

@Component({
  selector: 'app-dashboard-widget',
  standalone: true,
  imports: [DraggableDirective, NzTabsModule, NzIconDirective, NzGridModule, DroppableDirective, CdkDropListGroup, CdkDropList, CdkDrag, NgStyle, NgClass, ResizableModule],
  templateUrl: './dashboard-widget.component.html',
  styleUrl: './dashboard-widget.component.less',
  styles: [
    `
      mwlResizable {
        box-sizing: border-box; // required for the enableGhostResize option to work
      }
    `
  ]
})
export class DashboardWidgetComponent implements AfterViewInit {
  @Input() widget!: WidgetConfig;
  @Output() readonly resizeWidget = new EventEmitter();
  leftPanelWidth: number = 340;
  isResize: boolean = false;

  constructor(private readonly cdr: ChangeDetectorRef) { }

  onResizeStart(event: ResizeEvent): void {
    this.isResize = true;
  }

  onResizeEnd(event: ResizeEvent): void {
    this.updateWidgetLayoutPosition(event);
    this.isResize = false;
  }

  updateWidgetLayoutPosition(event: ResizeEvent): void {
    if (this.widget.layout) {
      // get top parent element -- right design container
      const rightContainer: HTMLElement = document.querySelector(`#${this.widget.tag}`)!.parentElement!.parentElement!;
      // get left menu
      const menuSidebar: HTMLElement = document.querySelector(`#menuNav`)!;
      this.widget.layout.left = this.toPercentage((event.rectangle.left - this.leftPanelWidth - menuSidebar.clientWidth) / rightContainer.clientWidth);
      this.widget.layout.top = this.toPercentage((event.rectangle.top - rightContainer.offsetTop) / rightContainer.clientHeight);
      this.widget.layout.height = this.toPercentage(event.rectangle.height! / rightContainer.clientHeight);
      this.widget.layout.width = this.toPercentage(event.rectangle.width! / rightContainer.clientWidth);
      this.resizeWidget.emit({ layout: this.widget.layout, tag: this.widget.tag });
    }
  }

  dragStarted(event: CdkDragStart<WidgetConfig>): void {
    if (this.isResize) {
      event.event.preventDefault();
      return;
    }
  }

  toPercentage(num: number): string {
    return `${Number(100 * num).toFixed(2)}%`;
  }

  checkAccept(element: HTMLElement): boolean {
    return element.classList.contains('inner-box');
  }

  getPercentageLayout(widgetElementRef: ElementRef<HTMLElement>, moveX: number, moveY: number): LayoutPosition {
    // get top parent element -- right design container
    const rightContainer: HTMLElement = document.querySelector(`#${this.widget.tag}`)!.parentElement!.parentElement!;
    const widgetElement: HTMLElement = widgetElementRef.nativeElement;
    const left: number = widgetElement.parentElement!.offsetLeft;
    const top: number = widgetElement.parentElement!.offsetTop;
    const width: number = widgetElement.offsetWidth;
    const height: number = widgetElement.offsetHeight;
    const containerHeight: number = rightContainer.offsetHeight;
    const containerWidth: number = rightContainer.offsetWidth;

    return {
      left: this.toPercentage((left + moveX - 300) / containerWidth),
      top: this.toPercentage(top / containerHeight),
      width: this.toPercentage(width / containerWidth),
      height: this.toPercentage(height / containerHeight)
    };
  }

  setLayoutPositionForElement(element: HTMLElement): void {
    if (!this.widget.layout) {
      return;
    }

    element.style.top = this.widget.layout.top;
    element.style.left = this.widget.layout.left;
  }

  dropWidget(event: CdkDragDrop<WidgetConfig[]>): void {
    this.setLayoutPositionForElement(event.item.element.nativeElement);
    if (this.isResize) {
      event.event.preventDefault();
      return;
    }

    const moveX: number = event.dropPoint.x - event.distance.x;
    const moveY: number = event.dropPoint.y - event.distance.y;
    const mouseEvent: MouseEvent = event.event as MouseEvent;
    const layoutPosition = this.getPercentageLayout(event.item.element, moveX, moveY);
    const layout: LayoutPosition = {
      left: `${mouseEvent.layerX - event.item.element.nativeElement.clientWidth / 2}px`,
      top: `${mouseEvent.layerY - event.item.element.nativeElement.clientHeight / 2}px`,
      width: layoutPosition.width,
      height: layoutPosition.height
    };

    this.widget.layout = layout;
  }

  ngAfterViewInit(): void {
    if (this.widget.configuration) {

    }
  }
}
